package com.millstein.tsinglog.config;

import com.millstein.tsinglog.interceptor.ShiroUserFilter;
import com.millstein.tsinglog.shiro.realm.CustomRealm;
import com.millstein.tsinglog.shiro.session.CustomSessionManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    // 1.创建realm
    @Bean
    public CustomRealm buildCustomRealm() {
        return new CustomRealm();
    }

    // 2.创建SecurityManager
    @Bean
    public SecurityManager buildSecurityManager(CustomRealm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);

        // 配置会话管理器（不配置的话默认是ServletContainerSessionManager）
        securityManager.setSessionManager(this.buildDefaultWebSessionManager());
        // 配置缓存管理器
        securityManager.setCacheManager(this.buildRedisCacheManager());
        return securityManager;
    }

    // 3.创建shiroFilter工厂
    @Bean
    public ShiroFilterFactoryBean buildShiroFilterFactoryBean(SecurityManager securityManager) {
        // 1.创建过滤器工厂
        ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();

        // 自定义拦截器的配置
        Map<String, Filter> filter = new HashMap<>();
        filter.put("custom", new ShiroUserFilter());
        filterFactory.setFilters(filter);
        // 2.设置SecurityManager
        filterFactory.setSecurityManager(securityManager);
        // 3.通用配置
        filterFactory.setLoginUrl("/login");
        filterFactory.setUnauthorizedUrl("/unauthorized");
        // 4.设置过滤器集合
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/user/login", "anon");
        filterMap.put("/user/logout", "logout");
        filterMap.put("/**", "custom");

        filterFactory.setFilterChainDefinitionMap(filterMap);

        return filterFactory;
    }

    // 4.开启shiro注解支持
//    @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
//        return new LifecycleBeanPostProcessor();
//    }
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor buildAuthorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }




    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;

    // 5.配置会话管理器
    // 5.1.配置redis控制器，操作redis
    public RedisManager buildRedisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        return redisManager;
    }

    // 5.2.配置sessionDao
    public RedisSessionDAO buildRedisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(this.buildRedisManager());
        return redisSessionDAO;
    }

    // 5.3.配置会话管理器
    public DefaultWebSessionManager buildDefaultWebSessionManager() {
        CustomSessionManager customSessionManager = new CustomSessionManager();
        customSessionManager.setSessionDAO(this.buildRedisSessionDAO());
//        customSessionManager.setGlobalSessionTimeout(1000 * 60);
        return customSessionManager;
    }

    // 5.4.配置缓存管理器（使用redis）
    public RedisCacheManager buildRedisCacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(this.buildRedisManager());
        return redisCacheManager;
    }
}
